
<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta charset="utf-8" />
    <title>bdsim.blockdiagram &#8212; Block diagram simulation 0.7 documentation</title>
    <link rel="stylesheet" href="../../_static/alabaster.css" type="text/css" />
    <link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
    <link rel="stylesheet" type="text/css" href="../../_static/graphviz.css" />
    <script id="documentation_options" data-url_root="../../" src="../../_static/documentation_options.js"></script>
    <script src="../../_static/jquery.js"></script>
    <script src="../../_static/underscore.js"></script>
    <script src="../../_static/doctools.js"></script>
    <script src="../../_static/language_data.js"></script>
    <script async="async" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=TeX-AMS-MML_HTMLorMML"></script>
    <link rel="index" title="Index" href="../../genindex.html" />
    <link rel="search" title="Search" href="../../search.html" />
   
  <link rel="stylesheet" href="../../_static/custom.css" type="text/css" />
  
  
  <meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />

  </head><body>
  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          

          <div class="body" role="main">
            
  <h1>Source code for bdsim.blockdiagram</h1><div class="highlight"><pre>
<span></span><span class="ch">#!/usr/bin/env python3</span>
<span class="c1"># -*- coding: utf-8 -*-</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd">Created on Mon May 18 21:43:18 2020</span>

<span class="sd">@author: corkep</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">os.path</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">importlib</span>
<span class="kn">import</span> <span class="nn">inspect</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">import</span> <span class="nn">argparse</span>
<span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">Counter</span><span class="p">,</span> <span class="n">namedtuple</span>
<span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
<span class="kn">import</span> <span class="nn">scipy.integrate</span> <span class="k">as</span> <span class="nn">integrate</span>
<span class="kn">import</span> <span class="nn">matplotlib</span>
<span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>

<span class="kn">from</span> <span class="nn">bdsim.components</span> <span class="kn">import</span> <span class="o">*</span>

<span class="n">debuglist</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1"># (&#39;propagate&#39;, &#39;state&#39;, &#39;deriv&#39;)</span>

<div class="viewcode-block" id="DEBUG"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.DEBUG">[docs]</a><span class="k">def</span> <span class="nf">DEBUG</span><span class="p">(</span><span class="n">debug</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">debug</span> <span class="ow">in</span> <span class="n">debuglist</span><span class="p">:</span>
        <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;DEBUG.</span><span class="si">{:s}</span><span class="s1">: &#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">debug</span><span class="p">),</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span></div>

<span class="c1"># print a progress bar</span>
<span class="c1"># https://stackoverflow.com/questions/3173320/text-progress-bar-in-the-console</span>
<div class="viewcode-block" id="printProgressBar"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.printProgressBar">[docs]</a><span class="k">def</span> <span class="nf">printProgressBar</span> <span class="p">(</span><span class="n">fraction</span><span class="p">,</span> <span class="n">prefix</span><span class="o">=</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="n">suffix</span><span class="o">=</span><span class="s1">&#39;&#39;</span><span class="p">,</span> <span class="n">decimals</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">length</span><span class="o">=</span><span class="mi">50</span><span class="p">,</span> <span class="n">fill</span> <span class="o">=</span> <span class="s1">&#39;█&#39;</span><span class="p">,</span> <span class="n">printEnd</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="se">\r</span><span class="s2">&quot;</span><span class="p">):</span>
    
    <span class="n">percent</span> <span class="o">=</span> <span class="p">(</span><span class="s2">&quot;{0:.&quot;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">decimals</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&quot;f}&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">fraction</span> <span class="o">*</span> <span class="mi">100</span><span class="p">)</span>
    <span class="n">filledLength</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">length</span> <span class="o">*</span> <span class="n">fraction</span><span class="p">)</span>
    <span class="n">bar</span> <span class="o">=</span> <span class="n">fill</span> <span class="o">*</span> <span class="n">filledLength</span> <span class="o">+</span> <span class="s1">&#39;-&#39;</span> <span class="o">*</span> <span class="p">(</span><span class="n">length</span> <span class="o">-</span> <span class="n">filledLength</span><span class="p">)</span>
    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;</span><span class="se">\r</span><span class="si">{</span><span class="n">prefix</span><span class="si">}</span><span class="s1"> |</span><span class="si">{</span><span class="n">bar</span><span class="si">}</span><span class="s1">| </span><span class="si">{</span><span class="n">percent</span><span class="si">}</span><span class="s1">% </span><span class="si">{</span><span class="n">suffix</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">,</span> <span class="n">end</span> <span class="o">=</span> <span class="n">printEnd</span><span class="p">)</span></div>

<span class="c1"># convert class name to BLOCK name</span>
<div class="viewcode-block" id="blockname"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.blockname">[docs]</a><span class="k">def</span> <span class="nf">blockname</span><span class="p">(</span><span class="bp">cls</span><span class="p">):</span>
    <span class="k">return</span> <span class="bp">cls</span><span class="o">.</span><span class="vm">__name__</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s1">&#39;_&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span></div>
<span class="c1"># ------------------------------------------------------------------------- #    </span>


<div class="viewcode-block" id="BlockDiagram"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.BlockDiagram">[docs]</a><span class="k">class</span> <span class="nc">BlockDiagram</span><span class="p">:</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Block diagram class.  This object is the parent of all blocks and wires in </span>
<span class="sd">    the system.</span>
<span class="sd">    </span>
<span class="sd">    :ivar wirelist: all wires in the diagram</span>
<span class="sd">    :vartype wirelist: list of Wire instances</span>
<span class="sd">    :ivar blocklist: all blocks in the diagram</span>
<span class="sd">    :vartype blocklist: list of Block subclass instances</span>
<span class="sd">    :ivar x: state vector</span>
<span class="sd">    :vartype x: np.ndarray</span>
<span class="sd">    :ivar compiled: diagram has successfully compiled</span>
<span class="sd">    :vartype compiled: bool</span>
<span class="sd">    :ivar T: maximum simulation time (seconds)</span>
<span class="sd">    :vartype T: float</span>
<span class="sd">    :ivar t: current simulation time (seconds)</span>
<span class="sd">    :vartype t: float</span>
<span class="sd">    :ivar fignum: number of next matplotlib figure to create</span>
<span class="sd">    :vartype fignum: int</span>
<span class="sd">    :ivar stop: reference to block wanting to stop simulation, else None</span>
<span class="sd">    :vartype stop: Block subclass</span>
<span class="sd">    :ivar checkfinite: halt simulation if any wire has inf or nan</span>
<span class="sd">    :vartype checkfinite: bool</span>
<span class="sd">    :ivar blockcounter: unique counter for each block type</span>
<span class="sd">    :vartype blockcounter: collections.Counter</span>
<span class="sd">    :ivar blockdict: index of all blocks by category</span>
<span class="sd">    :vartype blockdict: dict of lists</span>
<span class="sd">    :ivar name: name of this diagram</span>
<span class="sd">    :vartype name: str</span>
<span class="sd">    :ivar graphics: enable graphics</span>
<span class="sd">    :vartype graphics: bool</span>
<span class="sd">    &quot;&quot;&quot;</span>
    
    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;main&#39;</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :param name: diagram name, defaults to &#39;main&#39;</span>
<span class="sd">        :type name: str, optional</span>
<span class="sd">        :param sysargs: process options from sys.argv, defaults to True</span>
<span class="sd">        :type sysargs: bool, optional</span>
<span class="sd">        :param graphics: enable graphics, defaults to True</span>
<span class="sd">        :type graphics: bool, optional</span>
<span class="sd">        :param animation: enable animation, defaults to False</span>
<span class="sd">        :type animation: bool, optional</span>
<span class="sd">        :param progress: enable progress bar, defaults to True</span>
<span class="sd">        :type progress: bool, optional</span>
<span class="sd">        :param debug: debug options, defaults to None</span>
<span class="sd">        :type debug: str, optional</span>
<span class="sd">        :param backend: matplotlib backend, defaults to &#39;Qt5Agg&#39;&#39;</span>
<span class="sd">        :type backend: str, optional</span>
<span class="sd">        :param tiles: figure tile layout on monitor, defaults to &#39;3x4&#39;</span>
<span class="sd">        :type tiles: str, optional</span>
<span class="sd">        :raises ImportError: syntax error in block</span>
<span class="sd">        :return: parent object for blockdiagram</span>
<span class="sd">        :rtype: BlockDiagram</span>
<span class="sd">        </span>
<span class="sd">        The instance has a number of factory methods that return instances of blocks.</span>
<span class="sd">        </span>
<span class="sd">        ===================  =========  ========  ===========================================</span>
<span class="sd">        Command line switch  Argument   Default   Behaviour</span>
<span class="sd">        ===================  =========  ========  ===========================================</span>
<span class="sd">        --nographics, -g     graphics   True      enable graphical display</span>
<span class="sd">        --animation, -a      animation  False     update graphics at each time step</span>
<span class="sd">        --noprogress, -p     progress   True      display simulation progress bar</span>
<span class="sd">        --backend BE         backend    &#39;Qt5Agg&#39;  matplotlib backend</span>
<span class="sd">        --tiles RxC, -t RxC  tiles      &#39;3x4&#39;     arrangement of figure tiles on the display</span>
<span class="sd">        --debug F, -d F      debug      &#39;&#39;        debug flag string</span>
<span class="sd">        ===================  =========  ========  ===========================================</span>
<span class="sd">        </span>
<span class="sd">        The debug string comprises single letter flags:</span>
<span class="sd">            </span>
<span class="sd">            - &#39;p&#39; debug network value propagation</span>
<span class="sd">            - &#39;s&#39; debug state vector</span>
<span class="sd">            - &#39;d&#39; debug state derivative </span>

<span class="sd">        &quot;&quot;&quot;</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">wirelist</span> <span class="o">=</span> <span class="p">[]</span>      <span class="c1"># list of all wires</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span> <span class="o">=</span> <span class="p">[]</span>     <span class="c1"># list of all blocks</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">x</span> <span class="o">=</span> <span class="kc">None</span>           <span class="c1"># state vector numpy.ndarray</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">compiled</span> <span class="o">=</span> <span class="kc">False</span>   <span class="c1"># network has been compiled</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">T</span> <span class="o">=</span> <span class="kc">None</span>           <span class="c1"># maximum.BlockDiagram time</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">t</span> <span class="o">=</span> <span class="kc">None</span>           <span class="c1"># current time</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">fignum</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">stop</span> <span class="o">=</span> <span class="kc">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">checkfinite</span> <span class="o">=</span> <span class="kc">True</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">blockcounter</span> <span class="o">=</span> <span class="n">Counter</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>

        <span class="c1"># process command line and constructor options</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_get_options</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>

        <span class="c1">##load modules from the blocks folder</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_load_modules</span><span class="p">()</span>
        
        
    <span class="k">def</span> <span class="nf">_get_options</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sysargs</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        
        <span class="c1"># all switches and their default values</span>
        <span class="n">defaults</span> <span class="o">=</span> <span class="p">{</span>
            <span class="s1">&#39;backend&#39;</span><span class="p">:</span> <span class="s1">&#39;Qt5Agg&#39;</span><span class="p">,</span>
            <span class="s1">&#39;tiles&#39;</span><span class="p">:</span> <span class="s1">&#39;3x4&#39;</span><span class="p">,</span>
            <span class="s1">&#39;graphics&#39;</span><span class="p">:</span> <span class="kc">True</span><span class="p">,</span>
            <span class="s1">&#39;animation&#39;</span><span class="p">:</span> <span class="kc">False</span><span class="p">,</span>
            <span class="s1">&#39;progress&#39;</span><span class="p">:</span> <span class="kc">True</span><span class="p">,</span>
            <span class="s1">&#39;debug&#39;</span><span class="p">:</span> <span class="s1">&#39;&#39;</span>
            <span class="p">}</span>
        
        <span class="k">if</span> <span class="n">sysargs</span><span class="p">:</span>
            <span class="c1"># command line arguments and graphics</span>
            <span class="n">parser</span> <span class="o">=</span> <span class="n">argparse</span><span class="o">.</span><span class="n">ArgumentParser</span><span class="p">()</span>
            <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">&#39;--backend&#39;</span><span class="p">,</span> <span class="s1">&#39;-b&#39;</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">str</span><span class="p">,</span> <span class="n">metavar</span><span class="o">=</span><span class="s1">&#39;BACKEND&#39;</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="n">defaults</span><span class="p">[</span><span class="s1">&#39;backend&#39;</span><span class="p">],</span>
                                <span class="n">help</span><span class="o">=</span><span class="s1">&#39;matplotlib backend to choose&#39;</span><span class="p">)</span>
            <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">&#39;--tiles&#39;</span><span class="p">,</span> <span class="s1">&#39;-t&#39;</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">str</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="n">defaults</span><span class="p">[</span><span class="s1">&#39;tiles&#39;</span><span class="p">],</span> <span class="n">metavar</span><span class="o">=</span><span class="s1">&#39;ROWSxCOLS&#39;</span><span class="p">,</span>
                                <span class="n">help</span><span class="o">=</span><span class="s1">&#39;window tiling as NxM&#39;</span><span class="p">)</span>
            <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">&#39;--nographics&#39;</span><span class="p">,</span> <span class="s1">&#39;-g&#39;</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="n">defaults</span><span class="p">[</span><span class="s1">&#39;graphics&#39;</span><span class="p">],</span> <span class="n">action</span><span class="o">=</span><span class="s1">&#39;store_const&#39;</span><span class="p">,</span> <span class="n">const</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="s1">&#39;graphics&#39;</span><span class="p">,</span>
                                <span class="n">help</span><span class="o">=</span><span class="s1">&#39;disable graphic display&#39;</span><span class="p">)</span>
            <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">&#39;--animation&#39;</span><span class="p">,</span> <span class="s1">&#39;-a&#39;</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="n">defaults</span><span class="p">[</span><span class="s1">&#39;animation&#39;</span><span class="p">],</span> <span class="n">action</span><span class="o">=</span><span class="s1">&#39;store_const&#39;</span><span class="p">,</span> <span class="n">const</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
                                <span class="n">help</span><span class="o">=</span><span class="s1">&#39;animate graphics&#39;</span><span class="p">)</span>
            <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">&#39;--noprogress&#39;</span><span class="p">,</span> <span class="s1">&#39;-p&#39;</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="n">defaults</span><span class="p">[</span><span class="s1">&#39;progress&#39;</span><span class="p">],</span> <span class="n">action</span><span class="o">=</span><span class="s1">&#39;store_const&#39;</span><span class="p">,</span> <span class="n">const</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="s1">&#39;progress&#39;</span><span class="p">,</span>
                        <span class="n">help</span><span class="o">=</span><span class="s1">&#39;animate graphics&#39;</span><span class="p">)</span>
            <span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">&#39;--debug&#39;</span><span class="p">,</span> <span class="s1">&#39;-d&#39;</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">str</span><span class="p">,</span> <span class="n">metavar</span><span class="o">=</span><span class="s1">&#39;[psd]&#39;</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="n">defaults</span><span class="p">[</span><span class="s1">&#39;debug&#39;</span><span class="p">],</span> 
                                <span class="n">help</span><span class="o">=</span><span class="s1">&#39;debug flags&#39;</span><span class="p">)</span>
            <span class="n">clargs</span> <span class="o">=</span> <span class="nb">vars</span><span class="p">(</span><span class="n">parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">())</span>  <span class="c1"># get args as a dictionary</span>

            
        <span class="c1"># function arguments override the command line options</span>
        <span class="c1"># provide a list of argument names and default values</span>
        <span class="n">options</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="k">for</span> <span class="n">option</span><span class="p">,</span> <span class="n">default</span> <span class="ow">in</span> <span class="n">defaults</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
            <span class="k">if</span> <span class="n">option</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="p">:</span>
                <span class="c1"># first priority is to constructor argument</span>
                <span class="k">assert</span> <span class="nb">type</span><span class="p">(</span><span class="n">kwargs</span><span class="p">[</span><span class="n">option</span><span class="p">])</span> <span class="ow">is</span> <span class="nb">type</span><span class="p">(</span><span class="n">default</span><span class="p">),</span> <span class="s1">&#39;passed argument &#39;</span> <span class="o">+</span> <span class="n">opt</span> <span class="o">+</span> <span class="s1">&#39; has wrong type&#39;</span>
                <span class="n">options</span><span class="p">[</span><span class="n">option</span><span class="p">]</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="n">option</span><span class="p">]</span>
            <span class="k">elif</span> <span class="n">sysargs</span> <span class="ow">and</span> <span class="n">option</span> <span class="ow">in</span> <span class="n">clargs</span><span class="p">:</span>
                <span class="c1"># if not provided, drop through to command line argument</span>
                <span class="n">options</span><span class="p">[</span><span class="n">option</span><span class="p">]</span> <span class="o">=</span> <span class="n">clargs</span><span class="p">[</span><span class="n">option</span><span class="p">]</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="c1"># drop through to the default value</span>
                <span class="n">options</span><span class="p">[</span><span class="n">option</span><span class="p">]</span> <span class="o">=</span> <span class="n">default</span>
            
        <span class="c1"># ensure graphics is enabled if animation is requested</span>
        <span class="k">if</span> <span class="n">options</span><span class="p">[</span><span class="s1">&#39;animation&#39;</span><span class="p">]:</span>
            <span class="n">options</span><span class="p">[</span><span class="s1">&#39;graphics&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
        
        <span class="c1"># stash these away as a named tuple</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">options</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s1">&#39;options&#39;</span><span class="p">,</span> <span class="n">options</span><span class="o">.</span><span class="n">keys</span><span class="p">(),</span> <span class="n">defaults</span><span class="o">=</span><span class="nb">list</span><span class="p">(</span><span class="n">defaults</span><span class="o">.</span><span class="n">values</span><span class="p">()))()</span>
        
        <span class="c1"># setup debug parameters from single character codes</span>
        <span class="k">global</span> <span class="n">debuglist</span>
        <span class="k">if</span> <span class="s1">&#39;p&#39;</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">debug</span><span class="p">:</span>
            <span class="n">debuglist</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;propagate&#39;</span><span class="p">)</span>
        <span class="k">if</span> <span class="s1">&#39;s&#39;</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">debug</span><span class="p">:</span>
            <span class="n">debuglist</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;state&#39;</span><span class="p">)</span>
        <span class="k">if</span> <span class="s1">&#39;d&#39;</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">debug</span><span class="p">:</span>
            <span class="n">debuglist</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;deriv&#39;</span><span class="p">)</span>
            
    <span class="k">def</span> <span class="nf">_load_modules</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">nblocks</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">blocklist</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">nblocks</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Loading blocks:&#39;</span><span class="p">)</span>

            <span class="k">for</span> <span class="n">file</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="vm">__file__</span><span class="p">),</span> <span class="s1">&#39;blocks&#39;</span><span class="p">)):</span>
                <span class="c1"># scan every file ./blocks/*.py to find block definitions</span>
                <span class="c1"># a block is a class that subclasses Source, Sink, Function, Transfer and</span>
                <span class="c1"># has an @block decorator.</span>
                <span class="c1">#</span>
                <span class="c1"># The decorator adds the classes to a global variable blocklist in the</span>
                <span class="c1"># component module&#39;s namespace.</span>
                <span class="k">if</span> <span class="ow">not</span> <span class="n">file</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">&#39;test_&#39;</span><span class="p">)</span> <span class="ow">and</span> <span class="n">file</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s1">&#39;.py&#39;</span><span class="p">):</span>
                    <span class="c1"># valid python module, import it</span>
                    <span class="k">try</span><span class="p">:</span>
                        <span class="n">module</span> <span class="o">=</span> <span class="n">importlib</span><span class="o">.</span><span class="n">import_module</span><span class="p">(</span><span class="s1">&#39;.&#39;</span> <span class="o">+</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">splitext</span><span class="p">(</span><span class="n">file</span><span class="p">)[</span><span class="mi">0</span><span class="p">],</span> <span class="n">package</span><span class="o">=</span><span class="s1">&#39;bdsim.blocks&#39;</span><span class="p">)</span>
                    <span class="k">except</span> <span class="ne">SyntaxError</span><span class="p">:</span>
                        <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;-- syntax error in block definiton: &#39;</span> <span class="o">+</span> <span class="n">file</span><span class="p">)</span>
    
                    <span class="c1"># components.blocklist grows with every block import</span>
                    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">blocklist</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">nblocks</span><span class="p">:</span>
                        <span class="c1"># we just loaded some more blocks</span>
                        <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;  loading blocks from </span><span class="si">{:s}</span><span class="s1">: </span><span class="si">{:s}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="s1">&#39;, &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="n">blockname</span><span class="p">(</span><span class="bp">cls</span><span class="p">)</span> <span class="k">for</span> <span class="bp">cls</span> <span class="ow">in</span> <span class="n">blocklist</span><span class="p">[</span><span class="n">nblocks</span><span class="p">:]])))</span>
                        
                    <span class="c1"># perform basic sanity checks on the blocks just read</span>
                    <span class="k">for</span> <span class="bp">cls</span> <span class="ow">in</span> <span class="n">blocklist</span><span class="p">[</span><span class="n">nblocks</span><span class="p">:]:</span>
                        
                        <span class="k">if</span> <span class="bp">cls</span><span class="o">.</span><span class="n">blockclass</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">&#39;source&#39;</span><span class="p">,</span> <span class="s1">&#39;transfer&#39;</span><span class="p">,</span> <span class="s1">&#39;function&#39;</span><span class="p">):</span>
                            <span class="c1"># must have an output function</span>
                            <span class="n">valid</span> <span class="o">=</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="s1">&#39;output&#39;</span><span class="p">)</span> <span class="ow">and</span> \
                                    <span class="n">callable</span><span class="p">(</span><span class="bp">cls</span><span class="o">.</span><span class="n">output</span><span class="p">)</span> <span class="ow">and</span> \
                                    <span class="nb">len</span><span class="p">(</span><span class="n">inspect</span><span class="o">.</span><span class="n">signature</span><span class="p">(</span><span class="bp">cls</span><span class="o">.</span><span class="n">output</span><span class="p">)</span><span class="o">.</span><span class="n">parameters</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span>
                            <span class="k">if</span> <span class="ow">not</span> <span class="n">valid</span><span class="p">:</span>
                                <span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;class </span><span class="si">{:s}</span><span class="s1"> has missing/improper output method&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="bp">cls</span><span class="p">)))</span>
                            
                        <span class="k">if</span> <span class="bp">cls</span><span class="o">.</span><span class="n">blockclass</span> <span class="o">==</span> <span class="s1">&#39;sink&#39;</span><span class="p">:</span>
                            <span class="c1"># must have a step function</span>
                            <span class="n">valid</span> <span class="o">=</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="s1">&#39;step&#39;</span><span class="p">)</span> <span class="ow">and</span> \
                                    <span class="n">callable</span><span class="p">(</span><span class="bp">cls</span><span class="o">.</span><span class="n">step</span><span class="p">)</span> <span class="ow">and</span> \
                                    <span class="nb">len</span><span class="p">(</span><span class="n">inspect</span><span class="o">.</span><span class="n">signature</span><span class="p">(</span><span class="bp">cls</span><span class="o">.</span><span class="n">step</span><span class="p">)</span><span class="o">.</span><span class="n">parameters</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span>
                            <span class="k">if</span> <span class="ow">not</span> <span class="n">valid</span><span class="p">:</span>
                                <span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;class </span><span class="si">{:s}</span><span class="s1"> has missing/improper step method&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="bp">cls</span><span class="p">)))</span>
                                
                    <span class="n">nblocks</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">blocklist</span><span class="p">)</span>
        
        <span class="k">def</span> <span class="nf">new_method</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">bd</span><span class="p">):</span>
            <span class="k">def</span> <span class="nf">block_init_wrapper</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
                <span class="n">block</span> <span class="o">=</span> <span class="bp">cls</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="n">bd</span><span class="o">=</span><span class="n">bd</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">add_block</span><span class="p">(</span><span class="n">block</span><span class="p">)</span>
                <span class="k">return</span> <span class="n">block</span>
            
            <span class="c1"># return a function that invokes the class constructor</span>
            <span class="n">f</span> <span class="o">=</span> <span class="n">block_init_wrapper</span>
            <span class="c1"># move the __init__ docstring to the class to allow BLOCK.__doc__</span>
            <span class="bp">cls</span><span class="o">.</span><span class="vm">__doc__</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="fm">__init__</span><span class="o">.</span><span class="vm">__doc__</span>  
            <span class="k">return</span> <span class="n">f</span>
        
        <span class="c1"># bind the block constructors as new methods on this instance</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">blockdict</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="k">for</span> <span class="bp">cls</span> <span class="ow">in</span> <span class="n">blocklist</span><span class="p">:</span>
            <span class="c1"># create a function to invoke the block&#39;s constructor</span>
            <span class="n">f</span> <span class="o">=</span> <span class="n">new_method</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>
            
            <span class="c1"># create the new method name, strip underscores and capitalize</span>
            <span class="n">bindname</span> <span class="o">=</span> <span class="n">blockname</span><span class="p">(</span><span class="bp">cls</span><span class="p">)</span>
            
            <span class="c1"># set a bound version of this function as an attribute of the instance</span>
            <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bindname</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="fm">__get__</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span>
            
            <span class="n">blocktype</span> <span class="o">=</span> <span class="bp">cls</span><span class="o">.</span><span class="vm">__module__</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;.&#39;</span><span class="p">)[</span><span class="mi">2</span><span class="p">]</span>
            <span class="k">if</span> <span class="n">blocktype</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blockdict</span><span class="p">:</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">blockdict</span><span class="p">[</span><span class="n">blocktype</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">bindname</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">blockdict</span><span class="p">[</span><span class="n">blocktype</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">bindname</span><span class="p">]</span>
            
<div class="viewcode-block" id="BlockDiagram.create_figure"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.BlockDiagram.create_figure">[docs]</a>    <span class="k">def</span> <span class="nf">create_figure</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>

        <span class="k">def</span> <span class="nf">move_figure</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
            <span class="sd">&quot;&quot;&quot;Move figure&#39;s upper left corner to pixel (x, y)&quot;&quot;&quot;</span>
            <span class="n">backend</span> <span class="o">=</span> <span class="n">matplotlib</span><span class="o">.</span><span class="n">get_backend</span><span class="p">()</span>
            <span class="k">if</span> <span class="n">backend</span> <span class="o">==</span> <span class="s1">&#39;TkAgg&#39;</span><span class="p">:</span>
                <span class="n">f</span><span class="o">.</span><span class="n">canvas</span><span class="o">.</span><span class="n">manager</span><span class="o">.</span><span class="n">window</span><span class="o">.</span><span class="n">wm_geometry</span><span class="p">(</span><span class="s2">&quot;+</span><span class="si">%d</span><span class="s2">+</span><span class="si">%d</span><span class="s2">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
            <span class="k">elif</span> <span class="n">backend</span> <span class="o">==</span> <span class="s1">&#39;WXAgg&#39;</span><span class="p">:</span>
                <span class="n">f</span><span class="o">.</span><span class="n">canvas</span><span class="o">.</span><span class="n">manager</span><span class="o">.</span><span class="n">window</span><span class="o">.</span><span class="n">SetPosition</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="c1"># This works for QT and GTK</span>
                <span class="c1"># You can also use window.setGeometry</span>
                <span class="n">f</span><span class="o">.</span><span class="n">canvas</span><span class="o">.</span><span class="n">manager</span><span class="o">.</span><span class="n">window</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
                
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">fignum</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="c1"># no figures yet created, lazy initialization</span>
            
            <span class="n">matplotlib</span><span class="o">.</span><span class="n">use</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">backend</span><span class="p">)</span>            
            <span class="n">mpl_backend</span> <span class="o">=</span> <span class="n">matplotlib</span><span class="o">.</span><span class="n">get_backend</span><span class="p">()</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;matplotlib backend is&#39;</span><span class="p">,</span> <span class="n">mpl_backend</span><span class="p">)</span>
            
            <span class="n">dpiscale</span> <span class="o">=</span> <span class="mi">1</span>
            <span class="k">if</span> <span class="n">mpl_backend</span> <span class="o">==</span> <span class="s1">&#39;Qt5Agg&#39;</span><span class="p">:</span>
                <span class="kn">from</span> <span class="nn">PyQt5</span> <span class="kn">import</span> <span class="n">QtWidgets</span>
                <span class="n">app</span> <span class="o">=</span> <span class="n">QtWidgets</span><span class="o">.</span><span class="n">QApplication</span><span class="p">([])</span>
                <span class="n">screen</span> <span class="o">=</span> <span class="n">app</span><span class="o">.</span><span class="n">primaryScreen</span><span class="p">()</span>
                <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Screen: </span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">screen</span><span class="o">.</span><span class="n">name</span><span class="p">())</span>
                <span class="n">size</span> <span class="o">=</span> <span class="n">screen</span><span class="o">.</span><span class="n">size</span><span class="p">()</span>
                <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Size: </span><span class="si">%d</span><span class="s1"> x </span><span class="si">%d</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">size</span><span class="o">.</span><span class="n">width</span><span class="p">(),</span> <span class="n">size</span><span class="o">.</span><span class="n">height</span><span class="p">()))</span>
                <span class="n">rect</span> <span class="o">=</span> <span class="n">screen</span><span class="o">.</span><span class="n">availableGeometry</span><span class="p">()</span>
                <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Available: </span><span class="si">%d</span><span class="s1"> x </span><span class="si">%d</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">rect</span><span class="o">.</span><span class="n">width</span><span class="p">(),</span> <span class="n">rect</span><span class="o">.</span><span class="n">height</span><span class="p">()))</span>
                <span class="n">sw</span> <span class="o">=</span> <span class="n">rect</span><span class="o">.</span><span class="n">width</span><span class="p">()</span>
                <span class="n">sh</span> <span class="o">=</span> <span class="n">rect</span><span class="o">.</span><span class="n">height</span><span class="p">()</span>
                <span class="c1">#dpi = screen.physicalDotsPerInch()</span>
                <span class="n">dpiscale</span> <span class="o">=</span> <span class="n">screen</span><span class="o">.</span><span class="n">devicePixelRatio</span><span class="p">()</span> <span class="c1"># is 2.0 for Mac laptop screen</span>
            <span class="k">elif</span> <span class="n">mpl_backend</span> <span class="o">==</span> <span class="s1">&#39;TkAgg&#39;</span><span class="p">:</span>
                <span class="n">window</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">get_current_fig_manager</span><span class="p">()</span><span class="o">.</span><span class="n">window</span>
                <span class="n">sw</span> <span class="o">=</span>  <span class="n">window</span><span class="o">.</span><span class="n">winfo_screenwidth</span><span class="p">()</span>
                <span class="n">sh</span> <span class="o">=</span>  <span class="n">window</span><span class="o">.</span><span class="n">winfo_screenheight</span><span class="p">()</span>
                <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Size: </span><span class="si">%d</span><span class="s1"> x </span><span class="si">%d</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">sw</span><span class="p">,</span> <span class="n">sh</span><span class="p">))</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">screensize_pix</span> <span class="o">=</span> <span class="p">(</span><span class="n">sw</span><span class="p">,</span> <span class="n">sh</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">tiles</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">tiles</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;x&#39;</span><span class="p">)]</span>
            
            <span class="c1"># create a figure at default size to get dpi (TODO better way?)</span>
            <span class="n">f</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">))</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">dpi</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">dpi</span> <span class="o">/</span> <span class="n">dpiscale</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;dpi&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">dpi</span><span class="p">)</span>
            
            <span class="c1"># compute fig size in inches (width, height)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">figsize</span> <span class="o">=</span> <span class="p">[</span> <span class="bp">self</span><span class="o">.</span><span class="n">screensize_pix</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">/</span> <span class="bp">self</span><span class="o">.</span><span class="n">tiles</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">/</span> <span class="bp">self</span><span class="o">.</span><span class="n">dpi</span> <span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">screensize_pix</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">/</span> <span class="bp">self</span><span class="o">.</span><span class="n">tiles</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">/</span> <span class="bp">self</span><span class="o">.</span><span class="n">dpi</span> <span class="p">]</span>
            
            <span class="c1"># resize the figure</span>
            <span class="c1">#plt.figure(num=f.number, figsize=self.figsize)</span>
            <span class="n">f</span><span class="o">.</span><span class="n">set_size_inches</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">figsize</span><span class="p">,</span> <span class="n">forward</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
            <span class="n">plt</span><span class="o">.</span><span class="n">ion</span><span class="p">()</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">f</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">figsize</span><span class="p">)</span>
            
        <span class="c1"># move the figure to right place on screen</span>
        <span class="n">row</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">fignum</span> <span class="o">//</span> <span class="bp">self</span><span class="o">.</span><span class="n">tiles</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
        <span class="n">col</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">fignum</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">tiles</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
        <span class="n">move_figure</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">col</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">figsize</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">dpi</span><span class="p">,</span> <span class="n">row</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">figsize</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">dpi</span><span class="p">)</span>
        
        <span class="bp">self</span><span class="o">.</span><span class="n">fignum</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="c1">#print(&#39;create figure&#39;, self.fignum, row, col)</span>
        <span class="k">return</span> <span class="n">f</span></div>
        
    
<div class="viewcode-block" id="BlockDiagram.add_block"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.BlockDiagram.add_block">[docs]</a>    <span class="k">def</span> <span class="nf">add_block</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">block</span><span class="p">):</span>
        <span class="n">block</span><span class="o">.</span><span class="n">id</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">block</span><span class="o">.</span><span class="n">name</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
            <span class="n">i</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">blockcounter</span><span class="p">[</span><span class="n">block</span><span class="o">.</span><span class="n">type</span><span class="p">]</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">blockcounter</span><span class="p">[</span><span class="n">block</span><span class="o">.</span><span class="n">type</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
            <span class="n">block</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">{:s}</span><span class="s2">.</span><span class="si">{:d}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">block</span><span class="o">.</span><span class="n">type</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span>
        <span class="n">block</span><span class="o">.</span><span class="n">bd</span> <span class="o">=</span> <span class="bp">self</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">block</span><span class="p">)</span>  <span class="c1"># add to the list of available blocks</span></div>
        
<div class="viewcode-block" id="BlockDiagram.add_wire"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.BlockDiagram.add_wire">[docs]</a>    <span class="k">def</span> <span class="nf">add_wire</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">wire</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
        <span class="n">wire</span><span class="o">.</span><span class="n">id</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">wirelist</span><span class="p">)</span>
        <span class="n">wire</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">wirelist</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">wire</span><span class="p">)</span></div>
    
    <span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s1">&#39;BlockDiagram: </span><span class="si">{:s}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
    
    <span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">+</span> <span class="s2">&quot; with </span><span class="si">{:d}</span><span class="s2"> blocks and </span><span class="si">{:d}</span><span class="s2"> wires&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">),</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">wirelist</span><span class="p">))</span>
        <span class="c1"># for block in self.blocklist:</span>
        <span class="c1">#     s += str(block) + &quot;\n&quot;</span>
        <span class="c1"># s += &quot;\n&quot;</span>
        <span class="c1"># for wire in self.wirelist:</span>
        <span class="c1">#     s += str(wire) + &quot;\n&quot;</span>
        <span class="c1"># return s.lstrip(&quot;\n&quot;)</span>
        
<div class="viewcode-block" id="BlockDiagram.ls"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.BlockDiagram.ls">[docs]</a>    <span class="k">def</span> <span class="nf">ls</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blockdict</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">{:12s}</span><span class="s1">: &#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">k</span><span class="p">),</span> <span class="s1">&#39;, &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">v</span><span class="p">))</span></div>
    
<div class="viewcode-block" id="BlockDiagram.connect"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.BlockDiagram.connect">[docs]</a>    <span class="k">def</span> <span class="nf">connect</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
        
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        TODO:</span>
<span class="sd">            s.connect(out[3], in1[2], in2[3])  # one to many</span>
<span class="sd">            block[1] = SigGen()  # use setitem</span>
<span class="sd">            block[1] = SumJunction(block2[3], block3[4]) * Gain(value=2)</span>
<span class="sd">        &quot;&quot;&quot;</span>
                
        <span class="n">start</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
        
        <span class="c1"># convert to default plug on port 0 if need be</span>
        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">Block</span><span class="p">):</span>
            <span class="n">start</span> <span class="o">=</span> <span class="n">Plug</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
        <span class="n">start</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="s1">&#39;start&#39;</span>

        <span class="k">for</span> <span class="n">end</span> <span class="ow">in</span> <span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span>
            <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">end</span><span class="p">,</span> <span class="n">Block</span><span class="p">):</span>
                <span class="n">end</span> <span class="o">=</span> <span class="n">Plug</span><span class="p">(</span><span class="n">end</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
            <span class="n">end</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="s1">&#39;end&#39;</span>
                    
            <span class="k">if</span> <span class="n">start</span><span class="o">.</span><span class="n">isslice</span> <span class="ow">and</span> <span class="n">end</span><span class="o">.</span><span class="n">isslice</span><span class="p">:</span>
                <span class="c1"># we have a bundle of signals</span>
                                
                <span class="k">assert</span> <span class="n">start</span><span class="o">.</span><span class="n">width</span> <span class="o">==</span> <span class="n">end</span><span class="o">.</span><span class="n">width</span><span class="p">,</span> <span class="s1">&#39;slice wires must have same width&#39;</span>
                
                <span class="k">for</span> <span class="p">(</span><span class="n">s</span><span class="p">,</span><span class="n">e</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">start</span><span class="o">.</span><span class="n">portlist</span><span class="p">,</span> <span class="n">end</span><span class="o">.</span><span class="n">portlist</span><span class="p">):</span>
                    <span class="n">wire</span> <span class="o">=</span> <span class="n">Wire</span><span class="p">(</span> <span class="n">Plug</span><span class="p">(</span><span class="n">start</span><span class="o">.</span><span class="n">block</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="s1">&#39;start&#39;</span><span class="p">),</span> <span class="n">Plug</span><span class="p">(</span><span class="n">end</span><span class="o">.</span><span class="n">block</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="s1">&#39;end&#39;</span><span class="p">),</span> <span class="n">name</span><span class="p">)</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">add_wire</span><span class="p">(</span><span class="n">wire</span><span class="p">)</span>
            <span class="k">elif</span> <span class="n">start</span><span class="o">.</span><span class="n">isslice</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">end</span><span class="o">.</span><span class="n">isslice</span><span class="p">:</span>
                <span class="c1"># bundle goint to a block</span>
                <span class="k">assert</span> <span class="n">start</span><span class="o">.</span><span class="n">width</span> <span class="o">==</span> <span class="n">start</span><span class="o">.</span><span class="n">block</span><span class="o">.</span><span class="n">nin</span><span class="p">,</span> <span class="s2">&quot;bundle width doesn&#39;t match number of input ports&quot;</span>
                <span class="k">for</span> <span class="n">inport</span><span class="p">,</span><span class="n">outport</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">start</span><span class="o">.</span><span class="n">portlist</span><span class="p">):</span>
                    <span class="n">wire</span> <span class="o">=</span> <span class="n">Wire</span><span class="p">(</span> <span class="n">Plug</span><span class="p">(</span><span class="n">start</span><span class="o">.</span><span class="n">block</span><span class="p">,</span> <span class="n">outport</span><span class="p">,</span> <span class="s1">&#39;start&#39;</span><span class="p">),</span> <span class="n">Plug</span><span class="p">(</span><span class="n">end</span><span class="o">.</span><span class="n">block</span><span class="p">,</span> <span class="n">inport</span><span class="p">,</span> <span class="s1">&#39;end&#39;</span><span class="p">),</span> <span class="n">name</span><span class="p">)</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">add_wire</span><span class="p">(</span><span class="n">wire</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">wire</span> <span class="o">=</span> <span class="n">Wire</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">add_wire</span><span class="p">(</span><span class="n">wire</span><span class="p">)</span></div>
        
<div class="viewcode-block" id="BlockDiagram.compile"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.BlockDiagram.compile">[docs]</a>    <span class="k">def</span> <span class="nf">compile</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">subsystem</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">doimport</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Compile the block diagram</span>
<span class="sd">        </span>
<span class="sd">        :param subsystem: importing a subsystems, defaults to False</span>
<span class="sd">        :type subsystem: bool, optional</span>
<span class="sd">        :param doimport: import subsystems, defaults to True</span>
<span class="sd">        :type doimport: bool, optional</span>
<span class="sd">        :raises RuntimeError: various block diagram errors</span>
<span class="sd">        :return: Compile status</span>
<span class="sd">        :rtype: bool</span>
<span class="sd">        </span>
<span class="sd">        Performs a number of operations:</span>
<span class="sd">            </span>
<span class="sd">            - Check sanity of block parameters</span>
<span class="sd">            - Recursively clone and import subsystems</span>
<span class="sd">            - Check for loops without dynamics</span>
<span class="sd">            - Check for inputs driven by more than one wire</span>
<span class="sd">            - Check for unconnected inputs and outputs</span>
<span class="sd">            - Link all output ports to outgoing wires</span>
<span class="sd">            - Link all input ports to incoming wires</span>
<span class="sd">            - Evaluate all blocks in the network</span>

<span class="sd">        &quot;&quot;&quot;</span>
        
        <span class="c1"># namethe elements</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">nblocks</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">)</span>
        <span class="c1"># for b in self.blocklist:</span>
        <span class="c1">#     if b.name is None:</span>
        <span class="c1">#         i = self.blockcounter[b.type]</span>
        <span class="c1">#         self.blockcounter[b.type] += 1</span>
        <span class="c1">#         b.name = &quot;{:s}.{:d}&quot;.format(b.type, i)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">nwires</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">wirelist</span><span class="p">)</span>
        <span class="c1"># for (i,w) in enumerate(self.wirelist):</span>
        <span class="c1">#     # w.id = i </span>
        <span class="c1">#     # if w.name is None:</span>
        <span class="c1">#     #     w.name = &quot;wire {:d}&quot;.format(i)</span>
        <span class="c1">#     if w.start.block.blockclass == &#39;source&#39;:</span>
        <span class="c1">#         w.blockclass = &#39;source&#39;</span>
        

        <span class="n">error</span> <span class="o">=</span> <span class="kc">False</span>
        
        <span class="bp">self</span><span class="o">.</span><span class="n">nstates</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">statenames</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">blocknames</span> <span class="o">=</span> <span class="p">{}</span>
        
        <span class="k">if</span> <span class="ow">not</span> <span class="n">subsystem</span><span class="p">:</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\n</span><span class="s1">Compiling:&#39;</span><span class="p">)</span>
        
        <span class="c1"># process all subsystem imports</span>
        <span class="n">ssblocks</span> <span class="o">=</span> <span class="p">[</span><span class="n">b</span> <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span> <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s1">&#39;subsystem&#39;</span><span class="p">]</span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">ssblocks</span><span class="p">:</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;  importing subsystem&#39;</span><span class="p">,</span> <span class="n">b</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">ssvar</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
                <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;-- Wiring in subsystem&#39;</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="s1">&#39;from module local variable &#39;</span><span class="p">,</span> <span class="n">b</span><span class="o">.</span><span class="n">ssvar</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_flatten</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="p">[</span><span class="n">b</span><span class="o">.</span><span class="n">name</span><span class="p">])</span>

        <span class="c1"># run block specific checks</span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="n">b</span><span class="o">.</span><span class="n">check</span><span class="p">()</span>
            <span class="k">except</span><span class="p">:</span>
                <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s1">&#39;block failed check &#39;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">b</span><span class="p">))</span>

        <span class="c1"># build a dictionary of all block names</span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">blocknames</span><span class="p">[</span><span class="n">b</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">b</span>
        
        <span class="c1"># visit all stateful blocks</span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">blockclass</span> <span class="o">==</span> <span class="s1">&#39;TransferBlock&#39;</span><span class="p">:</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">nstates</span> <span class="o">+=</span> <span class="n">b</span><span class="o">.</span><span class="n">nstates</span>
                <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">_state_names</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
                    <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">b</span><span class="o">.</span><span class="n">_state_names</span><span class="p">)</span> <span class="o">==</span> <span class="n">b</span><span class="o">.</span><span class="n">nstates</span><span class="p">,</span> <span class="s1">&#39;number of state names not consistent with number of states&#39;</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">statenames</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">b</span><span class="o">.</span><span class="n">_state_names</span><span class="p">)</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="c1"># create default state names</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">statenames</span><span class="o">.</span><span class="n">extend</span><span class="p">([</span><span class="n">b</span><span class="o">.</span><span class="n">name</span> <span class="o">+</span> <span class="s1">&#39;x&#39;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">b</span><span class="o">.</span><span class="n">nstates</span><span class="p">)])</span>

        <span class="c1"># initialize lists of input and output ports</span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="n">b</span><span class="o">.</span><span class="n">outports</span> <span class="o">=</span> <span class="p">[[]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">b</span><span class="o">.</span><span class="n">nout</span><span class="p">)]</span>
            <span class="n">b</span><span class="o">.</span><span class="n">inports</span> <span class="o">=</span> <span class="p">[</span><span class="kc">None</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">b</span><span class="o">.</span><span class="n">nin</span><span class="p">)]</span>
        
         
        <span class="c1"># connect the source and destination blocks to each wire</span>
        <span class="k">for</span> <span class="n">w</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">wirelist</span><span class="p">:</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="n">w</span><span class="o">.</span><span class="n">start</span><span class="o">.</span><span class="n">block</span><span class="o">.</span><span class="n">add_outport</span><span class="p">(</span><span class="n">w</span><span class="p">)</span>
                <span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">block</span><span class="o">.</span><span class="n">add_inport</span><span class="p">(</span><span class="n">w</span><span class="p">)</span>
            <span class="k">except</span><span class="p">:</span>
                <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;error connecting wire &#39;</span><span class="p">,</span> <span class="n">w</span><span class="o">.</span><span class="n">fullname</span> <span class="o">+</span> <span class="s1">&#39;: &#39;</span><span class="p">,</span> <span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()[</span><span class="mi">1</span><span class="p">])</span>
                <span class="n">error</span> <span class="o">=</span> <span class="kc">True</span>
            
        <span class="c1"># check connections every block </span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="c1"># check all inputs are connected</span>
            <span class="k">for</span> <span class="n">port</span><span class="p">,</span> <span class="n">connection</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">b</span><span class="o">.</span><span class="n">inports</span><span class="p">):</span>
                <span class="k">if</span> <span class="n">connection</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
                    <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;  ERROR: block </span><span class="si">{:s}</span><span class="s1"> input </span><span class="si">{:d}</span><span class="s1"> is not connected&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">b</span><span class="p">),</span> <span class="n">port</span><span class="p">))</span>
                    <span class="n">error</span> <span class="o">=</span> <span class="kc">True</span>
                    
            <span class="c1"># check all outputs are connected</span>
            <span class="k">for</span> <span class="n">port</span><span class="p">,</span><span class="n">connections</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">b</span><span class="o">.</span><span class="n">outports</span><span class="p">):</span>
                <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">connections</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                    <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;  WARNING: block </span><span class="si">{:s}</span><span class="s1"> output </span><span class="si">{:d}</span><span class="s1"> is not connected&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">b</span><span class="p">),</span> <span class="n">port</span><span class="p">))</span>
                    
            <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">_inport_names</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
                <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">b</span><span class="o">.</span><span class="n">_inport_names</span><span class="p">)</span> <span class="o">==</span> <span class="n">b</span><span class="o">.</span><span class="n">nin</span><span class="p">,</span> <span class="s1">&#39;incorrect number of input names given: &#39;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">_outport_names</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
                <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">b</span><span class="o">.</span><span class="n">_outport_names</span><span class="p">)</span> <span class="o">==</span> <span class="n">b</span><span class="o">.</span><span class="n">nout</span><span class="p">,</span> <span class="s1">&#39;incorrect number of output names given: &#39;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">_state_names</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
                <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">b</span><span class="o">.</span><span class="n">_state_names</span><span class="p">)</span> <span class="o">==</span> <span class="n">b</span><span class="o">.</span><span class="n">nstates</span><span class="p">,</span> <span class="s1">&#39;incorrect number of state names given: &#39;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
                    
        <span class="c1"># check for cycles of function blocks</span>
        <span class="k">def</span> <span class="nf">_DFS</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
            <span class="n">start</span> <span class="o">=</span> <span class="n">path</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
            <span class="n">tail</span> <span class="o">=</span> <span class="n">path</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
            <span class="k">for</span> <span class="n">outgoing</span> <span class="ow">in</span> <span class="n">tail</span><span class="o">.</span><span class="n">outports</span><span class="p">:</span>
                <span class="c1"># for every port on this block</span>
                <span class="k">for</span> <span class="n">w</span> <span class="ow">in</span> <span class="n">outgoing</span><span class="p">:</span>
                    <span class="n">dest</span> <span class="o">=</span> <span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">block</span>
                    <span class="k">if</span> <span class="n">dest</span> <span class="o">==</span> <span class="n">start</span><span class="p">:</span>
                        <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;  ERROR: cycle found: &#39;</span><span class="p">,</span> <span class="s1">&#39; - &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="n">dest</span><span class="p">]]))</span>
                        <span class="k">return</span> <span class="kc">True</span>
                    <span class="k">if</span> <span class="n">dest</span><span class="o">.</span><span class="n">blockclass</span> <span class="o">==</span> <span class="s1">&#39;function&#39;</span><span class="p">:</span>
                        <span class="k">return</span> <span class="n">_DFS</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="n">dest</span><span class="p">])</span> <span class="c1"># recurse</span>
            <span class="k">return</span> <span class="kc">False</span>

        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">blockclass</span> <span class="o">==</span> <span class="s1">&#39;function&#39;</span><span class="p">:</span>
                <span class="c1"># do depth first search looking for a cycle</span>
                <span class="k">if</span> <span class="n">_DFS</span><span class="p">([</span><span class="n">b</span><span class="p">]):</span>
                    <span class="n">error</span> <span class="o">=</span> <span class="kc">True</span>

        <span class="c1"># evaluate the network once to check out wire types</span>
        <span class="n">x</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">getstate</span><span class="p">()</span>
        
        <span class="k">try</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">evaluate</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="mf">0.0</span><span class="p">)</span>
        <span class="k">except</span> <span class="ne">RuntimeError</span> <span class="k">as</span> <span class="n">err</span><span class="p">:</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;unrecoverable error in value propagation:&#39;</span><span class="p">,</span> <span class="n">err</span><span class="p">)</span>
            <span class="n">error</span> <span class="o">=</span> <span class="kc">True</span>
            
        <span class="k">if</span> <span class="ow">not</span> <span class="n">error</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">compiled</span> <span class="o">=</span> <span class="kc">True</span>
            
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">compiled</span></div>
    
    <span class="c1">#flatten the hierarchy</span>
    
    <span class="k">def</span> <span class="nf">_flatten</span><span class="p">(</span><span class="n">top</span><span class="p">,</span> <span class="n">subsys</span><span class="p">,</span> <span class="n">path</span><span class="p">):</span>
        <span class="n">subsystems</span> <span class="o">=</span> <span class="p">[</span><span class="n">b</span> <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">subsys</span><span class="o">.</span><span class="n">subsystem</span><span class="o">.</span><span class="n">blocklist</span> <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s1">&#39;subsystem&#39;</span><span class="p">]</span>
        <span class="c1"># recursively flatten all subsystems</span>
        <span class="k">for</span> <span class="n">ss</span> <span class="ow">in</span> <span class="n">subsystems</span><span class="p">:</span>
            <span class="n">flatten</span><span class="p">(</span><span class="n">top</span><span class="p">,</span> <span class="n">ss</span><span class="p">,</span> <span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="n">ss</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="p">)</span>
        
        <span class="c1"># compile this subsystem TODO</span>
        <span class="k">if</span> <span class="n">subsys</span><span class="o">.</span><span class="n">subsystem</span><span class="o">.</span><span class="n">compiled</span> <span class="ow">is</span> <span class="kc">False</span><span class="p">:</span>
            <span class="n">ok</span> <span class="o">=</span> <span class="n">subsys</span><span class="o">.</span><span class="n">subsystem</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="n">subsystem</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="n">ok</span><span class="p">:</span>
                <span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;cant compile subsystem&#39;</span><span class="p">)</span>
        <span class="c1"># sort the subsystem blocks into categories</span>
        <span class="n">inports</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">outports</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">others</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">subsys</span><span class="o">.</span><span class="n">subsystem</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s1">&#39;inport&#39;</span><span class="p">:</span>
                <span class="n">inports</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
            <span class="k">elif</span> <span class="n">b</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s1">&#39;outport&#39;</span><span class="p">:</span>
                <span class="n">outports</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">others</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">inports</span><span class="p">)</span> <span class="o">&gt;</span><span class="mi">1</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;subsystem has more than one input port element&#39;</span><span class="p">)</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">outports</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;subsystem has more than one output port element&#39;</span><span class="p">)</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">inports</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">outports</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s1">&#39;subsystem has no input or output port elements&#39;</span><span class="p">)</span>
            
        <span class="c1"># connect the input port</span>
        <span class="n">inport</span> <span class="o">=</span> <span class="n">inports</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
        <span class="k">for</span> <span class="n">w</span> <span class="ow">in</span> <span class="n">top</span><span class="o">.</span><span class="n">wirelist</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">block</span> <span class="o">==</span> <span class="n">subsys</span><span class="p">:</span>
                <span class="c1"># this top-level wire is input to subsystem</span>
                <span class="c1"># reroute it</span>
                <span class="n">port</span> <span class="o">=</span> <span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">port</span>
                <span class="k">for</span> <span class="n">w2</span> <span class="ow">in</span> <span class="n">inport</span><span class="o">.</span><span class="n">outports</span><span class="p">[</span><span class="n">port</span><span class="p">]:</span>
                    <span class="c1"># w2 is the wire from INPORT to others within subsystem</span>
                    
                    <span class="c1"># make w2 start at the source driving INPORT</span>
                    <span class="n">w2</span><span class="o">.</span><span class="n">start</span><span class="o">.</span><span class="n">block</span> <span class="o">=</span> <span class="n">w</span><span class="o">.</span><span class="n">start</span><span class="o">.</span><span class="n">block</span>
                    <span class="n">w2</span><span class="o">.</span><span class="n">start</span><span class="o">.</span><span class="n">port</span> <span class="o">=</span> <span class="n">w</span><span class="o">.</span><span class="n">start</span><span class="o">.</span><span class="n">port</span>
        <span class="c1"># remove all wires connected to the inport</span>
        <span class="n">top</span><span class="o">.</span><span class="n">wirelist</span> <span class="o">=</span> <span class="p">[</span><span class="n">w</span> <span class="k">for</span> <span class="n">w</span> <span class="ow">in</span> <span class="n">top</span><span class="o">.</span><span class="n">wirelist</span> <span class="k">if</span> <span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">block</span> <span class="o">!=</span> <span class="n">subsys</span><span class="p">]</span>
                
        <span class="c1"># connect the output port</span>
        <span class="n">outport</span> <span class="o">=</span> <span class="n">outports</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
        <span class="k">for</span> <span class="n">w</span> <span class="ow">in</span> <span class="n">top</span><span class="o">.</span><span class="n">wirelist</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">w</span><span class="o">.</span><span class="n">start</span><span class="o">.</span><span class="n">block</span> <span class="o">==</span> <span class="n">subsys</span><span class="p">:</span>
                <span class="c1"># this top-level wire is output from subsystem</span>
                <span class="c1"># reroute it</span>
                <span class="n">port</span> <span class="o">=</span> <span class="n">w</span><span class="o">.</span><span class="n">start</span><span class="o">.</span><span class="n">port</span>
                <span class="n">w2</span> <span class="o">=</span> <span class="n">outport</span><span class="o">.</span><span class="n">inports</span><span class="p">[</span><span class="n">port</span><span class="p">]</span>
                <span class="c1"># w2 is the wire to OUTPORT from others within subsystem</span>
                
                <span class="c1"># make w2 end at the destination from OUTPORT</span>
                <span class="n">w2</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">block</span> <span class="o">=</span> <span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">block</span>
                <span class="n">w2</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">port</span> <span class="o">=</span> <span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">port</span>
        <span class="c1"># remove all wires connected to the outport</span>
        <span class="n">top</span><span class="o">.</span><span class="n">wirelist</span> <span class="o">=</span> <span class="p">[</span><span class="n">w</span> <span class="k">for</span> <span class="n">w</span> <span class="ow">in</span> <span class="n">top</span><span class="o">.</span><span class="n">wirelist</span> <span class="k">if</span> <span class="n">w</span><span class="o">.</span><span class="n">start</span><span class="o">.</span><span class="n">block</span> <span class="o">!=</span> <span class="n">subsys</span><span class="p">]</span>
        <span class="n">top</span><span class="o">.</span><span class="n">blocklist</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">subsys</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">others</span><span class="p">:</span>
            <span class="n">top</span><span class="o">.</span><span class="n">add_block</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>   <span class="c1"># add remaining blocks from subsystem</span>
            <span class="n">b</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="s1">&#39;/&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="p">[</span><span class="n">b</span><span class="o">.</span><span class="n">name</span><span class="p">])</span>
        <span class="n">top</span><span class="o">.</span><span class="n">wirelist</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">subsys</span><span class="o">.</span><span class="n">subsystem</span><span class="o">.</span><span class="n">wirelist</span><span class="p">)</span>  <span class="c1"># add remaining wires from subsystem</span>
        
<div class="viewcode-block" id="BlockDiagram.report"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.BlockDiagram.report">[docs]</a>    <span class="k">def</span> <span class="nf">report</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Print a tabular report about the block diagram</span>

<span class="sd">        &quot;&quot;&quot;</span>
        
        <span class="k">class</span> <span class="nc">TableFormat</span><span class="p">:</span>
            
            <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">table</span><span class="p">,</span> <span class="n">colsep</span> <span class="o">=</span> <span class="mi">2</span><span class="p">):</span>
                <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">                Tabular printing</span>
<span class="sd">                </span>
<span class="sd">                :param table: format string</span>
<span class="sd">                :type table: str</span>
<span class="sd">                :param extrasep: extra separation between columns, default 2</span>
<span class="sd">                :type extrasep: int</span>
<span class="sd">                :return: a format string</span>
<span class="sd">                :rtype: str</span>
<span class="sd">                </span>
<span class="sd">                Given an input string like::</span>
<span class="sd">                </span>
<span class="sd">                    &quot;col1[s] col2[d] col3[10s] col4[3d]&quot;</span>
<span class="sd">                    </span>
<span class="sd">                where the square brackets denote type  (as per `format`) and the</span>
<span class="sd">                number if given is a minumum column width.  The actual column width</span>
<span class="sd">                is the maximum of the given value and the width of the heading text</span>
<span class="sd">                plus `extrasep`.</span>
<span class="sd">                </span>
<span class="sd">                Then print the header and a separator line::</span>
<span class="sd">                </span>
<span class="sd">                col1  col2  col3        col4</span>
<span class="sd">                ----  ----  ----------  ----</span>
<span class="sd">    </span>
<span class="sd">                and return a format string that can be used with `format` to format</span>
<span class="sd">                the arguments for subsequent data rows.</span>
<span class="sd">                &quot;&quot;&quot;</span>
                <span class="c1"># parse the format line</span>
                <span class="n">re_fmt</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s2">&quot;([a-zA-Z]+)\[(\-?[0-9]*|\*)([a-z])\]&quot;</span><span class="p">)</span>
                
                <span class="n">colheads</span> <span class="o">=</span> <span class="p">[]</span>
                <span class="n">varwidth</span> <span class="o">=</span> <span class="p">{}</span>
                <span class="n">columns</span> <span class="o">=</span> <span class="p">[]</span>
                
                <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">col</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">table</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39; &#39;</span><span class="p">)):</span>
                    <span class="n">m</span> <span class="o">=</span> <span class="n">re_fmt</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="n">col</span><span class="p">)</span>
                    <span class="n">colhead</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
                    <span class="n">colwidth</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
                    <span class="k">if</span> <span class="n">colwidth</span> <span class="o">==</span> <span class="s1">&#39;&#39;</span><span class="p">:</span>
                        <span class="n">colwidth</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">colhead</span><span class="p">)</span> <span class="o">+</span> <span class="n">colsep</span>
                        <span class="n">coljust</span> <span class="o">=</span> <span class="s1">&#39;&lt;&#39;</span>
                    <span class="k">elif</span> <span class="n">colwidth</span> <span class="o">==</span> <span class="s1">&#39;*&#39;</span><span class="p">:</span>
                        <span class="n">varwidth</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
                        <span class="n">colwidth</span> <span class="o">=</span> <span class="kc">None</span>
                        <span class="n">coljust</span> <span class="o">=</span> <span class="s1">&#39;&lt;&#39;</span>
                    <span class="k">else</span><span class="p">:</span>
                        <span class="n">w</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">colwidth</span><span class="p">)</span>
                        <span class="k">if</span> <span class="n">w</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
                            <span class="n">coljust</span> <span class="o">=</span> <span class="s1">&#39;&gt;&#39;</span>
                            <span class="n">w</span> <span class="o">=</span> <span class="o">-</span><span class="n">w</span>
                        <span class="k">else</span><span class="p">:</span>
                            <span class="n">coljust</span> <span class="o">=</span> <span class="s1">&#39;&lt;&#39;</span>
                        <span class="n">colwidth</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">w</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">colhead</span><span class="p">)</span> <span class="o">+</span> <span class="n">colsep</span><span class="p">)</span>
                    <span class="n">colfmt</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
                    <span class="n">columns</span><span class="o">.</span><span class="n">append</span><span class="p">(</span> <span class="p">(</span><span class="n">colhead</span><span class="p">,</span> <span class="n">colfmt</span><span class="p">,</span> <span class="n">coljust</span><span class="p">,</span> <span class="n">colwidth</span><span class="p">)</span> <span class="p">)</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">ncols</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span>
                    
                <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="p">[]</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">colsep</span> <span class="o">=</span> <span class="n">colsep</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">columns</span> <span class="o">=</span> <span class="n">columns</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">varwidth</span> <span class="o">=</span> <span class="n">varwidth</span>

            
            <span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">data</span><span class="p">):</span>
                <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">ncols</span><span class="p">,</span> <span class="s1">&#39;wrong number of data items added&#39;</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
                <span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">varwidth</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">varwidth</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="n">k</span><span class="p">]))</span>
            
            <span class="k">def</span> <span class="nf">print</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
                <span class="n">hfmt</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span>
                <span class="n">cfmt</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span>
                <span class="n">sep</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span>
                
                <span class="n">colheads</span> <span class="o">=</span> <span class="p">[]</span>
                <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">col</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">columns</span><span class="p">):</span>
                    <span class="n">colhead</span><span class="p">,</span> <span class="n">colfmt</span><span class="p">,</span> <span class="n">coljust</span><span class="p">,</span> <span class="n">colwidth</span> <span class="o">=</span> <span class="n">col</span>
                    
                    <span class="n">colheads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">colhead</span><span class="p">)</span>
                    
                    <span class="k">if</span> <span class="n">colwidth</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
                        <span class="n">colwidth</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">varwidth</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
                        
                    <span class="k">if</span> <span class="n">colfmt</span> <span class="o">==</span> <span class="s1">&#39;d&#39;</span><span class="p">:</span>
                        <span class="n">hfmt</span> <span class="o">+=</span> <span class="s2">&quot;{:&gt;</span><span class="si">%d</span><span class="s2">s}&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">colwidth</span><span class="p">,)</span>
                    <span class="k">else</span><span class="p">:</span>
                        <span class="n">hfmt</span> <span class="o">+=</span> <span class="s2">&quot;{:</span><span class="si">%d</span><span class="s2">s}&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">colwidth</span><span class="p">,)</span>
                        
                    <span class="n">cfmt</span> <span class="o">+=</span> <span class="s2">&quot;{:</span><span class="si">%s%d%s</span><span class="s2">}&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">coljust</span><span class="p">,</span> <span class="n">colwidth</span><span class="p">,</span> <span class="n">colfmt</span><span class="p">)</span>
                    <span class="n">hfmt</span> <span class="o">+=</span> <span class="s1">&#39; &#39;</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">colsep</span>
                    <span class="n">cfmt</span> <span class="o">+=</span> <span class="s1">&#39; &#39;</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">colsep</span>
                    <span class="n">sep</span> <span class="o">+=</span> <span class="s1">&#39;-&#39;</span> <span class="o">*</span> <span class="n">colwidth</span> <span class="o">+</span> <span class="s1">&#39;  &#39;</span>
                    
                <span class="nb">print</span><span class="p">(</span><span class="n">hfmt</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="o">*</span><span class="n">colheads</span><span class="p">))</span>
                <span class="nb">print</span><span class="p">(</span><span class="n">sep</span><span class="p">)</span>
                
                <span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">:</span>
                    <span class="nb">print</span><span class="p">(</span> <span class="n">cfmt</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="o">*</span><span class="n">d</span><span class="p">))</span>
        
        <span class="c1"># print all the blocks</span>
        <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\n</span><span class="s1">Blocks::</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">)</span>
        <span class="n">cfmt</span> <span class="o">=</span> <span class="n">TableFormat</span><span class="p">(</span><span class="s2">&quot;id[3d] name[*s] nin[2d] nout[2d] nstate[2d]&quot;</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="n">cfmt</span><span class="o">.</span><span class="n">add</span><span class="p">(</span> <span class="n">b</span><span class="o">.</span><span class="n">id</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">b</span><span class="p">),</span> <span class="n">b</span><span class="o">.</span><span class="n">nin</span><span class="p">,</span> <span class="n">b</span><span class="o">.</span><span class="n">nout</span><span class="p">,</span> <span class="n">b</span><span class="o">.</span><span class="n">nstates</span><span class="p">)</span>
        <span class="n">cfmt</span><span class="o">.</span><span class="n">print</span><span class="p">()</span>
        
        <span class="c1"># print all the wires</span>
        <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\n</span><span class="s1">Wires::</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">)</span>
        <span class="n">cfmt</span> <span class="o">=</span> <span class="n">TableFormat</span><span class="p">(</span><span class="s2">&quot;id[3d] from[-6s] to[-6s] description[*s] type[*s]&quot;</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">w</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">wirelist</span><span class="p">:</span>
            <span class="n">start</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">{:d}</span><span class="s2">[</span><span class="si">{:d}</span><span class="s2">]&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">w</span><span class="o">.</span><span class="n">start</span><span class="o">.</span><span class="n">block</span><span class="o">.</span><span class="n">id</span><span class="p">,</span> <span class="n">w</span><span class="o">.</span><span class="n">start</span><span class="o">.</span><span class="n">port</span><span class="p">)</span>
            <span class="n">end</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">{:d}</span><span class="s2">[</span><span class="si">{:d}</span><span class="s2">]&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">block</span><span class="o">.</span><span class="n">id</span><span class="p">,</span> <span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">port</span><span class="p">)</span>
            
            <span class="n">value</span> <span class="o">=</span> <span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">block</span><span class="o">.</span><span class="n">inputs</span><span class="p">[</span><span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">port</span><span class="p">]</span>
            <span class="n">typ</span> <span class="o">=</span> <span class="nb">type</span><span class="p">(</span><span class="n">value</span><span class="p">)</span><span class="o">.</span><span class="vm">__name__</span>
            <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">np</span><span class="o">.</span><span class="n">ndarray</span><span class="p">):</span>
                <span class="n">typ</span> <span class="o">+=</span> <span class="s1">&#39; </span><span class="si">{:s}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">value</span><span class="o">.</span><span class="n">shape</span><span class="p">))</span>
            <span class="n">cfmt</span><span class="o">.</span><span class="n">add</span><span class="p">(</span> <span class="n">w</span><span class="o">.</span><span class="n">id</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">,</span> <span class="n">w</span><span class="o">.</span><span class="n">fullname</span><span class="p">,</span> <span class="n">typ</span><span class="p">)</span>
        <span class="n">cfmt</span><span class="o">.</span><span class="n">print</span><span class="p">()</span>
        <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\n</span><span class="s1">State variables: </span><span class="si">{:d}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">nstates</span><span class="p">))</span>
        
        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">compiled</span><span class="p">:</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;** System has not been compiled, or had a compile time error&#39;</span><span class="p">)</span></div>
            
<div class="viewcode-block" id="BlockDiagram.getstate"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.BlockDiagram.getstate">[docs]</a>    <span class="k">def</span> <span class="nf">getstate</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="c1"># get the state from each stateful block</span>
        <span class="n">x0</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([])</span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">blockclass</span> <span class="o">==</span> <span class="s1">&#39;transfer&#39;</span><span class="p">:</span>
                <span class="n">x0</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">r_</span><span class="p">[</span><span class="n">x0</span><span class="p">,</span> <span class="n">b</span><span class="o">.</span><span class="n">getstate</span><span class="p">()]</span>
        <span class="c1">#print(&#39;x0&#39;, x0)</span>
        <span class="k">return</span> <span class="n">x0</span></div>
        
<div class="viewcode-block" id="BlockDiagram.run"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.BlockDiagram.run">[docs]</a>    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">T</span><span class="o">=</span><span class="mf">10.0</span><span class="p">,</span> <span class="n">dt</span><span class="o">=</span><span class="mf">0.1</span><span class="p">,</span> <span class="n">solver</span><span class="o">=</span><span class="s1">&#39;RK45&#39;</span><span class="p">,</span> 
            <span class="n">block</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">checkfinite</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">watch</span><span class="o">=</span><span class="p">[],</span>
            <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Run the block diagram</span>
<span class="sd">        </span>
<span class="sd">        :param T: maximum integration time, defaults to 10.0</span>
<span class="sd">        :type T: float, optional</span>
<span class="sd">        :param dt: maximum time step, defaults to 0.1</span>
<span class="sd">        :type dt: float, optional</span>
<span class="sd">        :param solver: integration method, defaults to ``RK45``</span>
<span class="sd">        :type solver: str, optional</span>
<span class="sd">        :param block: matplotlib block at end of run, default False</span>
<span class="sd">        :type block: bool</span>
<span class="sd">        :param checkfinite: error if inf or nan on any wire, default True</span>
<span class="sd">        :type checkfinite: bool</span>
<span class="sd">        :param watch: list of input ports to log</span>
<span class="sd">        :type watch: list</span>
<span class="sd">        :param ``**kwargs``: passed to ``scipy.integrate``</span>
<span class="sd">        :return: time history of signals and states</span>
<span class="sd">        :rtype: Sim class</span>
<span class="sd">        </span>
<span class="sd">        Assumes that the network has been compiled.</span>
<span class="sd">        </span>
<span class="sd">        Graphics display in all blocks can be disabled using the `graphics`</span>
<span class="sd">        option to the ``BlockDiagram`` instance.</span>
<span class="sd">        </span>
<span class="sd">        </span>
<span class="sd">        Results are returned in a class with attributes:</span>
<span class="sd">            </span>
<span class="sd">        - ``t`` the time vector: ndarray, shape=(M,)</span>
<span class="sd">        - ``x`` is the state vector: ndarray, shape=(M,N)</span>
<span class="sd">        - ``xnames`` is a list of the names of the states corresponding to columns of `x`, eg. &quot;plant.x0&quot;,</span>
<span class="sd">          defined for the block using the ``snames`` argument</span>
<span class="sd">        - ``uN&#39;` for a watched input where N is the index of the port mentioned in the ``watch`` argument</span>
<span class="sd">        - ``unames`` is a list of the names of the input ports being watched, same order as in ``watch`` argument</span>
<span class="sd">        </span>
<span class="sd">        If there are no dynamic elements in the diagram, ie. no states, then ``x`` and ``xnames`` are not</span>
<span class="sd">        present.</span>
<span class="sd">        </span>
<span class="sd">        The ``watch`` argument is a list of one or more input ports whose value during simulation</span>
<span class="sd">        will be recorded.  The elements of the list can be:</span>
<span class="sd">            - a ``Block`` reference, which is interpretted as input port 0</span>
<span class="sd">            - a ``Plug`` reference, ie. a block with an index or attribute</span>
<span class="sd">            - a string of the form &quot;block[i]&quot; which is port i of the block named block.</span>
<span class="sd">        </span>

<span class="sd">        &quot;&quot;&quot;</span>
        
        <span class="k">assert</span> <span class="bp">self</span><span class="o">.</span><span class="n">compiled</span><span class="p">,</span> <span class="s1">&#39;Network has not been compiled&#39;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">T</span> <span class="o">=</span> <span class="n">T</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">count</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">stop</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># allow any block to stop.BlockDiagram by setting this to the block&#39;s name</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">checkfinite</span> <span class="o">=</span> <span class="n">checkfinite</span>
        
        <span class="c1"># preproces the watchlist</span>
        <span class="n">pluglist</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">plugnamelist</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">re_block</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;(?P&lt;name&gt;[^[]+)(\[(?P&lt;port&gt;[0-9]+)\])&#39;</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">watch</span><span class="p">:</span>
            <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
                <span class="c1"># a name was given, with optional port number</span>
                <span class="n">m</span> <span class="o">=</span> <span class="n">re_block</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
                <span class="n">name</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s1">&#39;name&#39;</span><span class="p">)</span>
                <span class="n">port</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s1">&#39;port&#39;</span><span class="p">)</span>
                <span class="n">b</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocknames</span><span class="p">[</span><span class="n">name</span><span class="p">]</span>
                <span class="n">plug</span> <span class="o">=</span> <span class="n">b</span><span class="p">[</span><span class="n">port</span><span class="p">]</span>
            <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">Block</span><span class="p">):</span>
                <span class="c1"># a block was given, defaults to port 0</span>
                <span class="n">plug</span> <span class="o">=</span> <span class="n">n</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
            <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">Plug</span><span class="p">):</span>
                <span class="c1"># a plug was given</span>
                <span class="n">plug</span> <span class="o">=</span> <span class="n">n</span>
            <span class="n">pluglist</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">plug</span><span class="p">)</span>
            <span class="n">plugnamelist</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">plug</span><span class="p">))</span>

        <span class="k">try</span><span class="p">:</span>        
            <span class="c1"># tell all blocks we&#39;re doing a.BlockDiagram</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
    
            <span class="c1"># get initial state from the stateful blocks</span>
            <span class="n">x0</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">getstate</span><span class="p">()</span>
            <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">x0</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
                <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;initial state x0 = &#39;</span><span class="p">,</span> <span class="n">x0</span><span class="p">)</span>
    
            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">progress</span><span class="p">:</span>
                <span class="n">printProgressBar</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">prefix</span><span class="o">=</span><span class="s1">&#39;Progress:&#39;</span><span class="p">,</span> <span class="n">suffix</span><span class="o">=</span><span class="s1">&#39;complete&#39;</span><span class="p">,</span> <span class="n">length</span><span class="o">=</span><span class="mi">60</span><span class="p">)</span>

            <span class="c1"># out = scipy.integrate.solve_ivp.BlockDiagram._deriv, args=(self,), t_span=(0,T), y0=x0, </span>
            <span class="c1">#             method=solver, t_eval=np.linspace(0, T, 100), events=None, **kwargs)</span>
            <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">x0</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
                <span class="c1"># block diagram contains states, solve it using numerical integration</span>

                <span class="n">scipy_integrator</span> <span class="o">=</span> <span class="n">integrate</span><span class="o">.</span><span class="vm">__dict__</span><span class="p">[</span><span class="n">solver</span><span class="p">]</span>  <span class="c1"># get user specified integrator</span>

                <span class="n">integrator</span> <span class="o">=</span> <span class="n">scipy_integrator</span><span class="p">(</span><span class="k">lambda</span> <span class="n">t</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">evaluate</span><span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="n">t</span><span class="p">),</span>
                                              <span class="n">t0</span><span class="o">=</span><span class="mf">0.0</span><span class="p">,</span> <span class="n">y0</span><span class="o">=</span><span class="n">x0</span><span class="p">,</span> <span class="n">t_bound</span><span class="o">=</span><span class="n">T</span><span class="p">,</span> <span class="n">max_step</span><span class="o">=</span><span class="n">dt</span><span class="p">)</span>

                <span class="c1"># initialize list of time and states</span>
                <span class="n">tlist</span> <span class="o">=</span> <span class="p">[]</span>
                <span class="n">xlist</span> <span class="o">=</span> <span class="p">[]</span>
                <span class="n">plist</span> <span class="o">=</span> <span class="p">[[]</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">pluglist</span><span class="p">]</span>
                
                <span class="k">while</span> <span class="n">integrator</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="s1">&#39;running&#39;</span><span class="p">:</span>

                    <span class="c1"># step the integrator, calls _deriv multiple times</span>
                    <span class="n">integrator</span><span class="o">.</span><span class="n">step</span><span class="p">()</span>

                    <span class="k">if</span> <span class="n">integrator</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="s1">&#39;failed&#39;</span><span class="p">:</span>
                        <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;integration completed with failed status &#39;</span><span class="p">)</span>

                    <span class="c1"># stash the results</span>
                    <span class="n">tlist</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">integrator</span><span class="o">.</span><span class="n">t</span><span class="p">)</span>
                    <span class="n">xlist</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">integrator</span><span class="o">.</span><span class="n">y</span><span class="p">)</span>
                    
                    <span class="c1"># record the ports on the watchlist</span>
                    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">p</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">pluglist</span><span class="p">):</span>
                        <span class="n">plist</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">block</span><span class="o">.</span><span class="n">inputs</span><span class="p">[</span><span class="n">p</span><span class="o">.</span><span class="n">port</span><span class="p">])</span>
                    
                    <span class="c1"># update all blocks that need to know</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">step</span><span class="p">()</span>
                    
                    <span class="c1"># update the progress bar</span>
                    <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">progress</span><span class="p">:</span>
                        <span class="n">printProgressBar</span><span class="p">(</span><span class="n">integrator</span><span class="o">.</span><span class="n">t</span> <span class="o">/</span> <span class="n">T</span><span class="p">,</span> <span class="n">prefix</span><span class="o">=</span><span class="s1">&#39;Progress:&#39;</span><span class="p">,</span> <span class="n">suffix</span><span class="o">=</span><span class="s1">&#39;complete&#39;</span><span class="p">,</span> <span class="n">length</span><span class="o">=</span><span class="mi">60</span><span class="p">)</span>

                    <span class="c1"># has any block called a stop?</span>
                    <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stop</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
                        <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\n</span><span class="s1">--- stop requested at t=</span><span class="si">{:f}</span><span class="s1"> by </span><span class="si">{:s}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">t</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stop</span><span class="p">)))</span>
                        <span class="k">break</span>

                <span class="c1"># save buffered data in a Struct</span>
                <span class="n">out</span> <span class="o">=</span> <span class="n">Struct</span><span class="p">(</span><span class="s1">&#39;results&#39;</span><span class="p">)</span>
                <span class="n">out</span><span class="o">.</span><span class="n">t</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">tlist</span><span class="p">)</span>
                <span class="n">out</span><span class="o">.</span><span class="n">x</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">xlist</span><span class="p">)</span>
                <span class="n">out</span><span class="o">.</span><span class="n">xnames</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">statenames</span>
                <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">p</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">pluglist</span><span class="p">):</span>
                    <span class="n">out</span><span class="p">[</span><span class="s1">&#39;u&#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)]</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">plist</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
                <span class="n">out</span><span class="o">.</span><span class="n">unames</span> <span class="o">=</span> <span class="n">plugnamelist</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="c1"># block diagram has no states</span>
                
                <span class="c1"># initialize list of time and states</span>
                <span class="n">tlist</span> <span class="o">=</span> <span class="p">[]</span>
                <span class="n">plist</span> <span class="o">=</span> <span class="p">[[]</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">pluglist</span><span class="p">]</span>
                
                <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">np</span><span class="o">.</span><span class="n">arange</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">T</span><span class="p">,</span> <span class="n">dt</span><span class="p">):</span>  <span class="c1"># step through the time range</span>

                    <span class="c1"># evaluate the block diagram</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">evaluate</span><span class="p">([],</span> <span class="n">t</span><span class="p">)</span>

                    <span class="c1"># stash the results</span>
                    <span class="n">tlist</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">integrator</span><span class="o">.</span><span class="n">t</span><span class="p">)</span>
                    <span class="n">xlist</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">integrator</span><span class="o">.</span><span class="n">y</span><span class="p">)</span>
                    
                    <span class="c1"># record the ports on the watchlist</span>
                    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">p</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">pluglist</span><span class="p">):</span>
                        <span class="n">plist</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">block</span><span class="o">.</span><span class="n">inputs</span><span class="p">[</span><span class="n">p</span><span class="o">.</span><span class="n">port</span><span class="p">])</span>

                    <span class="c1"># update all blocks that need to know</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">step</span><span class="p">()</span>

                    <span class="c1"># update the progress bar</span>
                    <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">progress</span><span class="p">:</span>
                        <span class="n">printProgressBar</span><span class="p">(</span><span class="n">integrator</span><span class="o">.</span><span class="n">t</span> <span class="o">/</span> <span class="n">T</span><span class="p">,</span> <span class="n">prefix</span><span class="o">=</span><span class="s1">&#39;Progress:&#39;</span><span class="p">,</span> <span class="n">suffix</span><span class="o">=</span><span class="s1">&#39;complete&#39;</span><span class="p">,</span> <span class="n">length</span><span class="o">=</span><span class="mi">60</span><span class="p">)</span>
                        
                    <span class="c1"># has any block called a stop?</span>
                    <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stop</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
                        <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\n</span><span class="s1">--- stop requested at t=</span><span class="si">{:f}</span><span class="s1"> by </span><span class="si">{:s}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">t</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stop</span><span class="p">)))</span>
                        <span class="k">break</span>
                    
                <span class="c1"># save buffered data in a Struct</span>
                <span class="n">out</span> <span class="o">=</span> <span class="n">Struct</span><span class="p">(</span><span class="s1">&#39;results&#39;</span><span class="p">)</span>
                <span class="n">out</span><span class="o">.</span><span class="n">t</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">tlist</span><span class="p">)</span>
                <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">p</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">pluglist</span><span class="p">):</span>
                    <span class="n">out</span><span class="p">[</span><span class="s1">&#39;u&#39;</span><span class="o">+</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)]</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="n">plist</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
                <span class="n">out</span><span class="o">.</span><span class="n">unames</span> <span class="o">=</span> <span class="n">plugnamelist</span>
                
            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">progress</span><span class="p">:</span>
                <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\r</span><span class="s1">&#39;</span> <span class="o">+</span> <span class="s1">&#39; &#39;</span><span class="o">*</span> <span class="mi">90</span> <span class="o">+</span> <span class="s1">&#39;</span><span class="se">\r</span><span class="s1">&#39;</span><span class="p">)</span>
                
        <span class="k">except</span> <span class="ne">RuntimeError</span> <span class="k">as</span> <span class="n">err</span><span class="p">:</span>
            <span class="c1"># bad things happens, print a message and return no result</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;unrecoverable error in evaluation: &#39;</span><span class="p">,</span> <span class="n">err</span><span class="p">)</span>
            <span class="k">return</span> <span class="kc">None</span>

        <span class="c1"># pause until all graphics blocks close</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">done</span><span class="p">(</span><span class="n">block</span><span class="o">=</span><span class="n">block</span><span class="p">)</span>
        <span class="c1"># print(self.count, &#39; integrator steps&#39;)</span>
        
        <span class="k">return</span> <span class="n">out</span></div>
        

<div class="viewcode-block" id="BlockDiagram.evaluate"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.BlockDiagram.evaluate">[docs]</a>    <span class="k">def</span> <span class="nf">evaluate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">t</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Evaluate all blocks in the network</span>
<span class="sd">        </span>
<span class="sd">        :param x: state</span>
<span class="sd">        :type x: numpy.ndarray</span>
<span class="sd">        :param t: current time</span>
<span class="sd">        :type t: float</span>
<span class="sd">        :return: state derivative</span>
<span class="sd">        :rtype: numpy.ndarray</span>
<span class="sd">        </span>
<span class="sd">        Performs the following steps:</span>
<span class="sd">            </span>
<span class="sd">        1. Partition the state vector to all stateful blocks</span>
<span class="sd">        2. Propogate known block output ports to connected input ports</span>


<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c1">#print(&#39;in evaluate at t=&#39;, t)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">t</span> <span class="o">=</span> <span class="n">t</span>
        <span class="n">DEBUG</span><span class="p">(</span><span class="s1">&#39;state&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; t=&#39;</span><span class="p">,</span> <span class="n">t</span><span class="p">,</span> <span class="s1">&#39;, x=&#39;</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="s1">&#39;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&#39;</span><span class="p">)</span>
        
        <span class="c1"># reset all the blocks ready for the evalation</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">reset</span><span class="p">()</span>
        
        <span class="c1"># split the state vector to stateful blocks</span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">blockclass</span> <span class="o">==</span> <span class="s1">&#39;transfer&#39;</span><span class="p">:</span>
                <span class="n">x</span> <span class="o">=</span> <span class="n">b</span><span class="o">.</span><span class="n">setstate</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
        
        <span class="c1"># process blocks with initial outputs and propagate</span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">blockclass</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">&#39;source&#39;</span><span class="p">,</span> <span class="s1">&#39;transfer&#39;</span><span class="p">):</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">_propagate</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span>
                
        <span class="c1"># check we have values for all</span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">nin</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">b</span><span class="o">.</span><span class="n">done</span><span class="p">:</span>
                <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39; has incomplete inputs&#39;</span><span class="p">)</span>
            
        <span class="c1"># gather the derivative</span>
        <span class="n">YD</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">array</span><span class="p">([])</span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">blockclass</span> <span class="o">==</span> <span class="s1">&#39;transfer&#39;</span><span class="p">:</span>
                <span class="k">assert</span> <span class="n">b</span><span class="o">.</span><span class="n">updated</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39; has incomplete inputs&#39;</span>
                <span class="n">yd</span> <span class="o">=</span> <span class="n">b</span><span class="o">.</span><span class="n">deriv</span><span class="p">()</span><span class="o">.</span><span class="n">flatten</span><span class="p">()</span>
                <span class="n">YD</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">r_</span><span class="p">[</span><span class="n">YD</span><span class="p">,</span> <span class="n">yd</span><span class="p">]</span>
        <span class="n">DEBUG</span><span class="p">(</span><span class="s1">&#39;deriv&#39;</span><span class="p">,</span> <span class="n">YD</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">YD</span></div>

    <span class="k">def</span> <span class="nf">_propagate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">t</span><span class="p">,</span> <span class="n">depth</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Propagate values of a block to all connected inputs.</span>
<span class="sd">        </span>
<span class="sd">        :param b: Block with valid output</span>
<span class="sd">        :type b: Block</span>
<span class="sd">        :param t: current time</span>
<span class="sd">        :type t: float</span>

<span class="sd">        When all inputs to a block are available, its output can be computed</span>
<span class="sd">        using its `output` method (which may also be a function of time).</span>
<span class="sd">        </span>
<span class="sd">        This value is presented to each connected input port via its</span>
<span class="sd">        `setinput` method.  That method returns True if the block now has</span>
<span class="sd">        all its inputs defined, in which case we recurse.</span>

<span class="sd">        &quot;&quot;&quot;</span>
        
        <span class="c1"># check for a subsystem block here, recurse to evalute it</span>
        <span class="c1"># execute the subsystem to obtain its outputs</span>

        <span class="c1"># get output of block at time t</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">out</span> <span class="o">=</span> <span class="n">b</span><span class="o">.</span><span class="n">output</span><span class="p">(</span><span class="n">t</span><span class="p">)</span>
        <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">err</span><span class="p">:</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;--Error at t=</span><span class="si">{:f}</span><span class="s1"> when computing output of block </span><span class="si">{:s}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">b</span><span class="p">)))</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;  </span><span class="si">{}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">err</span><span class="p">))</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;  inputs were: &#39;</span><span class="p">,</span> <span class="n">b</span><span class="o">.</span><span class="n">inputs</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">nstates</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
                <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;  state was: &#39;</span><span class="p">,</span> <span class="n">b</span><span class="o">.</span><span class="n">x</span><span class="p">)</span>
            <span class="k">raise</span> <span class="ne">RuntimeError</span> <span class="kn">from</span> <span class="bp">None</span>

            
        <span class="n">DEBUG</span><span class="p">(</span><span class="s1">&#39;propagate&#39;</span><span class="p">,</span> <span class="s1">&#39;  &#39;</span><span class="o">*</span><span class="n">depth</span><span class="p">,</span> <span class="s1">&#39;propagating: </span><span class="si">{:s}</span><span class="s1"> @ t=</span><span class="si">{:.3f}</span><span class="s1">: output = &#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">b</span><span class="p">),</span><span class="n">t</span><span class="p">)</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">out</span><span class="p">))</span>

        <span class="c1"># check for validity</span>
        <span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">out</span><span class="p">,</span> <span class="nb">list</span><span class="p">)</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">out</span><span class="p">)</span> <span class="o">==</span> <span class="n">b</span><span class="o">.</span><span class="n">nout</span><span class="p">,</span> <span class="s1">&#39;block output is wrong type/length&#39;</span>
        <span class="c1"># TODO check output validity once at the start</span>
        
        <span class="c1"># check it has no nan or inf values</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">checkfinite</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">out</span><span class="p">,</span> <span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="nb">float</span><span class="p">,</span> <span class="n">np</span><span class="o">.</span><span class="n">ndarray</span><span class="p">))</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">np</span><span class="o">.</span><span class="n">isfinite</span><span class="p">(</span><span class="n">out</span><span class="p">)</span><span class="o">.</span><span class="n">any</span><span class="p">():</span>
            <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s1">&#39;block outputs nan&#39;</span><span class="p">)</span>
        
        <span class="c1"># propagate block outputs to all downstream connected blocks</span>
        <span class="k">for</span> <span class="p">(</span><span class="n">port</span><span class="p">,</span> <span class="n">outwires</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">b</span><span class="o">.</span><span class="n">outports</span><span class="p">):</span> <span class="c1"># every port</span>
            <span class="n">val</span> <span class="o">=</span> <span class="n">out</span><span class="p">[</span><span class="n">port</span><span class="p">]</span>
            <span class="k">for</span> <span class="n">w</span> <span class="ow">in</span> <span class="n">outwires</span><span class="p">:</span>     <span class="c1"># every wire</span>
                
                <span class="n">DEBUG</span><span class="p">(</span><span class="s1">&#39;propagate&#39;</span><span class="p">,</span> <span class="s1">&#39;  &#39;</span><span class="o">*</span><span class="n">depth</span><span class="p">,</span> <span class="s1">&#39;[&#39;</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="s1">&#39;] = &#39;</span><span class="p">,</span> <span class="n">val</span><span class="p">,</span> <span class="s1">&#39; --&gt; &#39;</span><span class="p">,</span> <span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">block</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="s1">&#39;[&#39;</span><span class="p">,</span> <span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">port</span><span class="p">,</span> <span class="s1">&#39;]&#39;</span><span class="p">)</span>
                
                <span class="k">if</span> <span class="n">w</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">val</span><span class="p">)</span> <span class="ow">and</span> <span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">block</span><span class="o">.</span><span class="n">blockclass</span> <span class="o">==</span> <span class="s1">&#39;function&#39;</span><span class="p">:</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">_propagate</span><span class="p">(</span><span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">block</span><span class="p">,</span> <span class="n">t</span><span class="p">,</span> <span class="n">depth</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
                
<div class="viewcode-block" id="BlockDiagram.reset"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.BlockDiagram.reset">[docs]</a>    <span class="k">def</span> <span class="nf">reset</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Reset conditions within every active block.  Most importantly, all</span>
<span class="sd">        inputs are marked as unknown.</span>
<span class="sd">        </span>
<span class="sd">        Invokes the `reset` method on all blocks.</span>

<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="n">b</span><span class="o">.</span><span class="n">reset</span><span class="p">()</span>     </div>
    
<div class="viewcode-block" id="BlockDiagram.step"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.BlockDiagram.step">[docs]</a>    <span class="k">def</span> <span class="nf">step</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Tell all blocks to take action on new inputs.  Relevant to Sink</span>
<span class="sd">        blocks only since they have no output function to be called.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c1"># TODO could be done by output method, even if no outputs</span>
        
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="n">b</span><span class="o">.</span><span class="n">step</span><span class="p">()</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span></div>

                    
<div class="viewcode-block" id="BlockDiagram.start"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.BlockDiagram.start">[docs]</a>    <span class="k">def</span> <span class="nf">start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Inform all active blocks that.BlockDiagram is about to start.  Open files,</span>
<span class="sd">        initialize graphics, etc.</span>
<span class="sd">        </span>
<span class="sd">        Invokes the `start` method on all blocks.</span>
<span class="sd">        </span>
<span class="sd">        &quot;&quot;&quot;</span>            
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="n">b</span><span class="o">.</span><span class="n">start</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
            <span class="k">except</span><span class="p">:</span>
                <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s1">&#39;error in start method of block: &#39;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39; - &#39;</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()[</span><span class="mi">1</span><span class="p">]))</span> <span class="kn">from</span> <span class="bp">None</span></div>
                
            
<div class="viewcode-block" id="BlockDiagram.done"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.BlockDiagram.done">[docs]</a>    <span class="k">def</span> <span class="nf">done</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Inform all active blocks that.BlockDiagram is complete.  Close files,</span>
<span class="sd">        graphics, etc.</span>
<span class="sd">        </span>
<span class="sd">        Invokes the `done` method on all blocks.</span>
<span class="sd">        </span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="n">b</span><span class="o">.</span><span class="n">done</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span></div>
            
<div class="viewcode-block" id="BlockDiagram.savefig"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.BlockDiagram.savefig">[docs]</a>    <span class="k">def</span> <span class="nf">savefig</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">format</span><span class="o">=</span><span class="s1">&#39;pdf&#39;</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">GraphicsBlock</span><span class="p">):</span>
                <span class="n">fname</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;.&#39;</span> <span class="o">+</span> <span class="nb">format</span>
                <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;saving </span><span class="si">{}</span><span class="s1"> -&gt; </span><span class="si">{}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">b</span><span class="p">),</span> <span class="n">fname</span><span class="p">))</span>
                <span class="n">b</span><span class="o">.</span><span class="n">savefig</span><span class="p">(</span><span class="n">fname</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span></div>
        
<div class="viewcode-block" id="BlockDiagram.dotfile"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.BlockDiagram.dotfile">[docs]</a>    <span class="k">def</span> <span class="nf">dotfile</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">file</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        Write a GraphViz dot file representing the network.</span>
<span class="sd">        </span>
<span class="sd">        :param file: Name of file to write to</span>
<span class="sd">        :type file: str</span>

<span class="sd">        The file can be processed using neato or dot::</span>
<span class="sd">            </span>
<span class="sd">            % dot -Tpng -o out.png dotfile.dot</span>

<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">file</span><span class="p">,</span> <span class="s1">&#39;w&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">file</span><span class="p">:</span>
            
            <span class="n">header</span> <span class="o">=</span> <span class="sa">r</span><span class="s2">&quot;&quot;&quot;digraph G {</span>

<span class="s2">    graph [splines=ortho, rankdir=LR]</span>
<span class="s2">    node [shape=box]</span>
<span class="s2">    </span>
<span class="s2">    &quot;&quot;&quot;</span>
            <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">header</span><span class="p">)</span>
            <span class="c1"># add the blocks</span>
            <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
                <span class="n">options</span> <span class="o">=</span> <span class="p">[]</span>
                <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">blockclass</span> <span class="o">==</span> <span class="s2">&quot;source&quot;</span><span class="p">:</span>
                    <span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;shape=box3d&quot;</span><span class="p">)</span>
                <span class="k">elif</span> <span class="n">b</span><span class="o">.</span><span class="n">blockclass</span> <span class="o">==</span> <span class="s2">&quot;sink&quot;</span><span class="p">:</span>
                    <span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;shape=folder&quot;</span><span class="p">)</span>
                <span class="k">elif</span> <span class="n">b</span><span class="o">.</span><span class="n">blockclass</span> <span class="o">==</span> <span class="s2">&quot;function&quot;</span><span class="p">:</span>
                    <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s1">&#39;gain&#39;</span><span class="p">:</span>
                        <span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;shape=triangle&quot;</span><span class="p">)</span>
                        <span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;orientation=-90&quot;</span><span class="p">)</span>
                        <span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;label=&quot;</span><span class="si">{:g}</span><span class="s1">&quot;&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">b</span><span class="o">.</span><span class="n">gain</span><span class="p">))</span>
                    <span class="k">elif</span> <span class="n">b</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s1">&#39;sum&#39;</span><span class="p">:</span>
                        <span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;shape=point&quot;</span><span class="p">)</span>
                <span class="k">elif</span> <span class="n">b</span><span class="o">.</span><span class="n">blockclass</span> <span class="o">==</span> <span class="s1">&#39;transfer&#39;</span><span class="p">:</span>
                    <span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;shape=component&quot;</span><span class="p">)</span>
                <span class="k">if</span> <span class="n">b</span><span class="o">.</span><span class="n">pos</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
                    <span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;pos=&quot;</span><span class="si">{:g}</span><span class="s1">,</span><span class="si">{:g}</span><span class="s1">!&quot;&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">b</span><span class="o">.</span><span class="n">pos</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">b</span><span class="o">.</span><span class="n">pos</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span>
                <span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;xlabel=&lt;&lt;BR/&gt;&lt;FONT POINT-SIZE=&quot;8&quot; COLOR=&quot;blue&quot;&gt;</span><span class="si">{:s}</span><span class="s1">&lt;/FONT&gt;&gt;&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">b</span><span class="o">.</span><span class="n">type</span><span class="p">))</span>
                <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\t</span><span class="s1">&quot;</span><span class="si">{:s}</span><span class="s1">&quot; [</span><span class="si">{:s}</span><span class="s1">]</span><span class="se">\n</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">b</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="s1">&#39;, &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">options</span><span class="p">)))</span>
            
            <span class="c1"># add the wires</span>
            <span class="k">for</span> <span class="n">w</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">wirelist</span><span class="p">:</span>
                <span class="n">options</span> <span class="o">=</span> <span class="p">[]</span>
                <span class="c1">#options.append(&#39;xlabel=&quot;{:s}&quot;&#39;.format(w.name))</span>
                <span class="k">if</span> <span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">block</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s1">&#39;sum&#39;</span><span class="p">:</span>
                    <span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;headlabel=&quot;</span><span class="si">{:s}</span><span class="s1"> &quot;&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">block</span><span class="o">.</span><span class="n">signs</span><span class="p">[</span><span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">port</span><span class="p">]))</span>
                <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\t</span><span class="s1">&quot;</span><span class="si">{:s}</span><span class="s1">&quot; -&gt; &quot;</span><span class="si">{:s}</span><span class="s1">&quot; [</span><span class="si">{:s}</span><span class="s1">]</span><span class="se">\n</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">w</span><span class="o">.</span><span class="n">start</span><span class="o">.</span><span class="n">block</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">w</span><span class="o">.</span><span class="n">end</span><span class="o">.</span><span class="n">block</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="s1">&#39;, &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">options</span><span class="p">)))</span>

            <span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s1">&#39;}</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">)</span></div>
            
<div class="viewcode-block" id="BlockDiagram.blockvalues"><a class="viewcode-back" href="../../bdsim.html#bdsim.blockdiagram.BlockDiagram.blockvalues">[docs]</a>    <span class="k">def</span> <span class="nf">blockvalues</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocklist</span><span class="p">:</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Block </span><span class="si">{:s}</span><span class="s1">:&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">b</span><span class="o">.</span><span class="n">name</span><span class="p">))</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;  inputs:  &#39;</span><span class="p">,</span> <span class="n">b</span><span class="o">.</span><span class="n">inputs</span><span class="p">)</span>
            <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;  outputs: &#39;</span><span class="p">,</span> <span class="n">b</span><span class="o">.</span><span class="n">output</span><span class="p">(</span><span class="n">t</span><span class="o">=</span><span class="mi">0</span><span class="p">))</span>  </div></div>
            
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
    
    <span class="kn">import</span> <span class="nn">pathlib</span>
    <span class="kn">import</span> <span class="nn">os.path</span>

    <span class="n">exec</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">pathlib</span><span class="o">.</span><span class="n">Path</span><span class="p">(</span><span class="vm">__file__</span><span class="p">)</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">absolute</span><span class="p">(),</span> <span class="s2">&quot;test_blockdiagram.py&quot;</span><span class="p">))</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>

</pre></div>

          </div>
          
        </div>
      </div>
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
<h1 class="logo"><a href="../../index.html">Block diagram simulation</a></h1>








<h3>Navigation</h3>
<p class="caption"><span class="caption-text">Code documentation:</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="../../bdsim.html">bdsim package</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../bdsim.blocks.html">Blocks</a></li>
</ul>

<div class="relations">
<h3>Related Topics</h3>
<ul>
  <li><a href="../../index.html">Documentation overview</a><ul>
  <li><a href="../index.html">Module code</a><ul>
  </ul></li>
  </ul></li>
</ul>
</div>
<div id="searchbox" style="display: none" role="search">
  <h3 id="searchlabel">Quick search</h3>
    <div class="searchformwrapper">
    <form class="search" action="../../search.html" method="get">
      <input type="text" name="q" aria-labelledby="searchlabel" />
      <input type="submit" value="Go" />
    </form>
    </div>
</div>
<script>$('#searchbox').show(0);</script>








        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="footer">
      &copy;2020, Peter Corke.
      
      |
      Powered by <a href="http://sphinx-doc.org/">Sphinx 2.4.4</a>
      &amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
      
    </div>

    

    
  </body>
</html>